package com.mazaiting.instructions.constants;

import com.mazaiting.classfile.constant.ConstantFactory;
import com.mazaiting.instructions.base.Index16Instruction;
import com.mazaiting.instructions.base.Index8Instruction;
import com.mazaiting.rtda.MtFrame;
import com.mazaiting.rtda.MtOperandStack;
import com.mazaiting.rtda.heap.MtConstant;
import com.mazaiting.rtda.heap.MtConstantPool;

/**
 * 加载运行时常量池指令
 *
 * @author mazaiting
 * @since 2021/8/17
 */
public class LdcInstruction {

    /**
     * 弹出常量池中的数据压入操作数栈
     * @param frame 栈帧
     * @param index 索引
     */
    public static void ldc(MtFrame frame, int index) {
        MtOperandStack stack = frame.getOperandStack();
        MtConstantPool pool = frame.getMethod().getMtClass().getConstantPool();
        MtConstant constant = pool.getConstant(index);
        switch (constant.getTag()) {
            case ConstantFactory.CONSTANT_INTEGER:
                stack.pushInt(((MtConstant.MtIntConstant)constant).getValue());
                break;
            case ConstantFactory.CONSTANT_FLOAT:
                stack.pushFloat(((MtConstant.MtFloatConstant)constant).getValue());
                break;
            default:
                throw new RuntimeException("todo: ldc!");
        }
    }

    public static class Ldc extends Index8Instruction {
        @Override
        public void execute(MtFrame frame) {
            ldc(frame, index);
        }

        @Override
        public String toString() {
            return "ldc";
        }
    }

    public static class LdcW extends Index16Instruction {
        @Override
        public void execute(MtFrame frame) {
            ldc(frame, index);
        }
    }

    public static class Ldc2W extends Index16Instruction {
        @Override
        public void execute(MtFrame frame) {
            MtOperandStack stack = frame.getOperandStack();
            MtConstantPool pool = frame.getMethod().getMtClass().getConstantPool();
            MtConstant constant = pool.getConstant(index);
            switch (constant.getTag()) {
                case ConstantFactory.CONSTANT_LONG:
                    stack.pushLong(((MtConstant.MtLongConstant)constant).getValue());
                    break;
                case ConstantFactory.CONSTANT_DOUBLE:
                    stack.pushDouble(((MtConstant.MtDoubleConstant)constant).getValue());
                    break;
                default:
                    throw new RuntimeException("java.lang.ClassFormatError");
            }
        }
    }
}


















